#include "Connect.h"

Connect::Connect()
{
	mPortNum = 3200;
	mServerIp = std::string("192.168.0.66");
}
Connect::~Connect()
{
	closesocket(mMonitorSocket);
}
void Connect::SetPortNum( int num )
{
	mPortNum = num;
}
void Connect::SetServerIp( std::string server_ip )
{
	mServerIp = server_ip;
}
bool Connect::StartConnect()
{
	WSADATA wsa;
	if(WSAStartup(MAKEWORD(2,2),&wsa)!=0)
	{
		std::cout<< "[Error] " << "Socket Initial Failed!\n";
		exit(-1);
	}
	else
	{
		std::cout<< "[Ok] " << "Socket Initial Successfully!\n";
	}

	mMonitorSocket = socket(AF_INET, SOCK_STREAM, 0);
	if( mMonitorSocket == SOCKET_ERROR )
	{
		std::cout<< "[Error] " << "Socket Creating Failed!\n";
		exit(-1);
	}
	else
	{
		std::cout<< "[Ok] " << "Socket Creating Successfully!\n";
	}

	sockaddr_in serveraddr;
	memset(&serveraddr, 0, sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_addr.s_addr = inet_addr( mServerIp.data() );
	serveraddr.sin_port = htons(mPortNum);

	if( connect( mMonitorSocket, (const sockaddr*)&serveraddr, sizeof(sockaddr))!=0 )
	{
		std::cout<< "[Error] " << "Connection to " << mServerIp << ":" << mPortNum << "!\n";
		closesocket(mMonitorSocket);
		exit(-1);
	}
	else
	{
		return true;
	}

// 	while( true )
// 	{
// 		GetMessage( mMonitorSocket );
// 	}
}
std::string Connect::SetBeamBallPos()
{
	std::string ballposx;
	std::string ballposy;
	std::string ballposz;
	std::cout<< "ball pos x: ";
	std::cin>> ballposx;
	std::cout<< "ball pos y: ";
	std::cin>> ballposy;
	std::cout<< "ball pos z: ";
	std::cin>> ballposz;
	return std::string("(ball (pos " + ballposx + ' ' + ballposy + ' ' + ballposz + "))");
}
std::string Connect::SetBeamBallPos( float x, float y, float z )
{
	char ballpos[100];
	sprintf_s( ballpos, "(ball (pos %.2f %.2f %.2f))", x, y, z );
	return std::string(ballpos);
}
void Connect::SendCommand( int ctype )
{
	std::string command = "";

	if( ctype == 1 )
	{
		command = SetBeamBallPos();
		SendMessage( mMonitorSocket, command );
	}
	else if( ctype == 2 )
	{
		command = "(kickOff Left)";
		SendMessage( mMonitorSocket, command );
	}
	else if( ctype == 3 )
	{
		command = "(kickOff Right)";
		SendMessage( mMonitorSocket, command );
	}
	else if( ctype == 4 )
	{
		command = "(playMode corner_kick_left)";
		SendMessage( mMonitorSocket, command );
		std::string ballpos = SetBeamBallPos( 1.5f, 1.5f, 0.0f );
		SendMessage( mMonitorSocket, ballpos );
	}
	else if( ctype == 5 )
	{
		command = "(playMode corner_kick_right)";
		SendMessage( mMonitorSocket, command );
		std::string ballpos = SetBeamBallPos( 1.5f, 1.5f, 0.0f );
		SendMessage( mMonitorSocket, ballpos );
	}
	else if( ctype == 6 )
	{
		command = "(playMode goal_kick_left)";
		SendMessage( mMonitorSocket, command );
		std::string ballpos = SetBeamBallPos( 1.5f, 1.5f, 0.0f );
		SendMessage( mMonitorSocket, ballpos );
	}
	else if( ctype == 7 )
	{
		command = "(playMode goal_kick_right)";
		SendMessage( mMonitorSocket, command );
		std::string ballpos = SetBeamBallPos( 1.5f, 1.5f, 0.0f );
		SendMessage( mMonitorSocket, ballpos );
	}
	else if( ctype == 8 )
	{
		command = "(playMode KickIn_Left)";
		SendMessage( mMonitorSocket, command );
		std::string ballpos = SetBeamBallPos( 1.5f, 1.5f, 0.0f );
		SendMessage( mMonitorSocket, ballpos );
	}	
	else if( ctype == 9 )
	{
		command = "(playMode KickIn_Right)";
		SendMessage( mMonitorSocket, command );
		std::string ballpos = SetBeamBallPos( 1.5f, 1.5f, 0.0f );
		SendMessage( mMonitorSocket, ballpos );
	}
	else if( ctype == 10 )
	{
		command = "(playMode GameOver)";
		SendMessage( mMonitorSocket, command );
	}
	else if( ctype == 11 )
	{
		command = "(playMode BeforeKickOff)";
		SendMessage( mMonitorSocket, command );
	}
}
bool Connect::GetMessage( SOCKET s )
{
	std::string msg;
	static char buffer[16*1024];
	unsigned int bytesRead = 0;
	while(bytesRead < sizeof(unsigned int))
	{
		int readResult = recv(s, buffer + bytesRead, sizeof(unsigned int) - bytesRead,0);
		if(readResult < 0)
			continue;
		bytesRead += readResult;
	}
	unsigned int msgLen = ntohl(*(unsigned int*)buffer);
	if(sizeof(unsigned int) + msgLen > sizeof(buffer))
	{
		return false;
	}
	unsigned int msgRead = bytesRead - sizeof(unsigned int);
	char *offset = buffer + bytesRead;
	while (msgRead < msgLen)
	{
		int readLen = sizeof(buffer) - msgRead;
		if(readLen > msgLen - msgRead)
			readLen = msgLen - msgRead;
		int readResult = recv(s, offset, readLen,0);
		if(readResult < 0)
			continue;
		msgRead += readResult;
		offset += readResult;
	}
	(*offset) = 0;
	msg = std::string(buffer+sizeof(unsigned int));

	std::cout<< msg << "\n";
	return true;
}

void Connect::SendMessage( SOCKET s, std::string msg )
{
	unsigned  int len = htonl(msg.size());
	std::string prefix( (const char*)&len, sizeof(unsigned int));
	std::string str =prefix+msg;
	if( send( s, str.data(), str.size(),0)>0 )
	{ 
		std::cout<< "[Ok] " << "Send Message:";

	}
	else
	{
		std::cout<< "[Error] " << "Sending Message Failed!\n";
	}
}